<?php
    class excel_model extends Model
    {
        private $write_flag = false;
        private $header_map = array();
        private $content = array();
        private $phpexcel;
        private $column_cnt = 0;
        private $row_cnt = 0;
        private static $avail_type = array(
            'pdf' => array('.pdf', 'application/pdf', 'PDF'), 
            'html' => array('.html', 'text/html', 'HTML'), 
            'xls' => array('.xls', 'application/msexcel', 'Excel5'), 
            'xlsx' => array('.xlsx', 'application/msexcel', 'Excel2007'),
            'csv' => array('.csv', 'text/csv', 'CSV')
        );
        
        public function __construct(){
            parent::__construct();
            $this->load->library('phpexcel');
            $this->phpexcel = new PHPExcel();
        }    
        
        public function get_file($filetype = 'pdf', $fname_refix = ''){
            if (!in_array($filetype, array_keys(self::$avail_type))) return;
            if (!$this->write_flag) return;
            //strip not valid fname chars
            $fname_prefix = preg_replace('/[\\/:*?"<>|]+/i', '', $fname_prefix);
    
            require_writer(self::$avail_type[$filetype][2]);
            $filename = tempnam('', 'stp');
            $writer_class = 'PHPExcel_Writer_' . self::$avail_type[$filetype][2];
            $writer = new $writer_class($this->phpexcel);
            $writer->save($filename);
            $truename = $fname_prefix . date('Y_m_d_H_i_s') . self::$avail_type[$filetype][0];
            $this->_send_header($filename, $truename, self::$avail_type[$filetype][1]);           
        }
        
        public function set_header_map($map = array()){
            $this->header_map = $map; 
        }
        
        public function set_content($info = array()){
            $this->content = array_merge($info, $this->content);
        }
         
        public function do_write(){
            if ($this->write_flag) return;
            if (!$this->_validate()) return;
            $this->write_flag = true;
            $this->phpexcel = new PHPExcel();
            //things setting sheet options
            $sheet = $this->phpexcel->getActiveSheet();
            $pointer_x = 0;
            $pointer_y = 1;
            foreach($this->header_map as &$map_value){
                $sheet->setCellValueByColumnAndRow($pointer_x, $pointer_y, $map_value);               
                ++$pointer_x;
            }
            $pointer_x = 0;
            ++$pointer_y;
            foreach($this->content as &$content_value){
                foreach(array_keys($this->header_map) as $map_key){
                    $sheet->setCellValueByColumnAndRow($pointer_x, $pointer_y, $content_value[$map_key]);
                    ++$pointer_x;
                }
                ++$pointer_y;
                $pointer_x = 0;     
            }
            $this->_set_style();
        }
        
        public function do_clear(){
            $this->write_flag = false;
            $this->content = array();
            $this->phpexcel = new PHPExcel();
            $this->column_cnt = 0;
            $this->row_cnt = 0;
        }
        
        private function _set_style(){
            $sheet = $this->phpexcel->getActiveSheet();
            $sheet->setTitle(date('Y-M-D') . '信息');
            $style_pagesetup = new PHPExcel_Worksheet_PageSetup();
            $style_pagesetup->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);
            $sheet->setPageSetup($style_pagesetup);
            for ($row_iter = $sheet->getRowIterator(); $row_iter->valid(); $row_iter->next()){
                $row = $row_iter->current();
                for($cell_iter = $row->getCellIterator(); $cell_iter->valid(); $cell_iter->next()){
                    $cell = $cell_iter->current();
                    if(!$cell) continue;
                    $cell_style = $sheet->getStyle($cell->getColumn() . $cell->getRow());
                    $cell_style->getBorders()->getLeft()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
                    $cell_style->getBorders()->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
                    $cell_style->getBorders()->getTop()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
                    $cell_style->getBorders()->getBottom()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
                    $cell_style->getAlignment()->setWrapText(true);
                    $cell_style->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
                    
                    if ('A' == $cell->getColumn()){
                        $cell_style->getBorders()->getLeft()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
                    }                    
                    elseif (($this->column_cnt - 1) == $cell_iter->key()){
                        $cell_style->getBorders()->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
                    }
                    
                    if (1 == $cell->getRow()){
                        $cell_style->getBorders()->getTop()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
                        $cell_style->getFont()->setBold(true);
                        $sheet->getColumnDimension($cell->getColumn())->setWidth(12.36);
                    }
                    elseif ($this->row_cnt == $cell->getRow()){
                        $cell_style->getBorders()->getBottom()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK); 
                    }
                }
            }
        }    
        
        private function _send_header($filename, $truename, $filetype){    
            header('Content-Description: File Transfer');
            header('Content-Type: ' . $filetype);
            header('Content-Disposition: attachment; filename='.$truename);
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
            header('Content-Length: ' . filesize($filename));
            ob_clean();
            flush();
            readfile($filename);
            unlink($filename);
            exit;               
        }   
        
        private function _validate(){
            $column_cnt = count($this->header_map);
            if ($column_cnt == 0) return false;
            $row_cnt = count($this->content);
            if ($row_cnt == 0) return true;
            $temp_cell_cnt = count($this->content, COUNT_RECURSIVE) - $row_cnt;
            if ($column_cnt != ($temp_cell_cnt / $row_cnt)) return false;
            $this->column_cnt = $column_cnt;
            $this->row_cnt = $row_cnt + 1;
            return true;
        } 
    }
?>
